home *** CD-ROM | disk | FTP | other *** search
- Program Nim( input, output );
-
- const
- NROWS = 18;
-
- var
- i : integer;
- key : char;
- pile : array[1..3] of integer;
- move : record
- ntaken, pileno : integer;
- end;
-
- function GameOver : boolean;
- begin
- gameover := ( pile[1] + pile[2] + pile[3] = 0 );
- end;
-
- procedure display;
- var
- start, row, col : integer;
- begin
- ClrScr;
- start := 0;
- for col := 1 to 3 do
- if pile[col] > start then
- start := pile[col];
-
- for row := start downto 1 do
- begin
- for col := 1 to 3 do
- if pile[col] >= row then
- write( ' __ ' )
- else
- write( ' ' );
- writeln;
- end;
-
- if start > 0 then
- writeln( pile[1]:4, pile[2]:6, pile[3]:6 );
-
- writeln;
- end;
-
- procedure signon;
- begin
- writeln;
- writeln( ' *** NIM *** ' );
- writeln;
- writeln( 'I will set up three piles of coins.' );
- writeln( 'To move, take any number of coins away from any pile.' );
- writeln( 'The player who clears the screen wins.' );
- writeln;
- write( 'Now hit any key to start:' );
-
- while NOT keypressed do
- ;
- key := readkey;
- writeln;
- end;
-
- Procedure hismove;
- var
- ok : boolean;
- begin
- repeat
- write( 'Pile (1,2 or 3)? ' );
- readln( move.pileno );
- ok := (move.pileno >= 1) AND (move.pileno <= 3);
- if ok then
- begin
- write( 'Number to take away? ' );
- readln( move.ntaken );
- ok := (move.ntaken >= 1) AND (move.ntaken <= pile[move.pileno]);
- end;
- if not ok then writeln( 'What??' );
- until ok;
- pile[ move.pileno ] := pile[ move.pileno ] - move.ntaken;
- end;
-
- Procedure mymove;
- var
- firstbit, x, i, j : integer;
- bit : array[1..3,1..4] of boolean;
- parity : array[1..4] of boolean;
- begin
- for i := 1 to 3 do
- begin
- x := pile[i];
- for j := 4 downto 1 do
- begin
- bit[i, j] := odd(x);
- x := x div 2;
- end;
- end;
-
- for i := 1 to 4 do
- parity[i] := bit[1,i] <> (bit[2,i] <> bit[3,i]);
-
- move.pileno := 1;
- move.ntaken := 0;
- if not ( parity[1] OR parity[2] OR parity[3] OR parity[4] ) then
- begin
- while pile[move.pileno] = 0 do
- move.pileno := move.pileno + 1;
- if pile[move.pileno] = 1 then
- move.ntaken := 1
- else
- move.ntaken := random( pile[move.pileno]-1 ) + 1;
- end
- else
- begin
- firstbit := 1;
- while not parity[firstbit] do
- firstbit := firstbit + 1;
- while not bit[move.pileno, firstbit] do
- move.pileno := move.pileno + 1;
- for i := firstbit to 4 do
- begin
- x := 1;
- for j := 3 downto i do
- x := x * 2;
- if parity[i] then
- if bit[move.pileno, i] then
- move.ntaken := move.ntaken + x
- else
- move.ntaken := move.ntaken - x;
- end;
- end;
- pile[move.pileno] := pile[move.pileno] - move.ntaken;
- end;
-
- Begin
- Randomize;
- Signon;
- repeat
- for i := 1 to 3 do pile[i] := random(10) + 6;
- display;
- repeat
- hismove;
- if gameover then
- writeln( 'Congratulations ... You win!' )
- else
- begin
- display;
- Writeln( 'My move is ...' );
- Delay( 1500 );
- mymove;
- display;
- writeln( move.ntaken:3, ' from pile', move.pileno:2 );
- if gameover then
- writeln( '*** I win! ***' );
- writeln;
- end;
- until gameover;
- write( 'Another game? (y/n) ' );
- repeat
- key := readkey;
- until (key = 'n') OR (key = 'y');
- until key = 'n';
- End.
-
-